/*
  FtpCommon.java
*/

import java.util.*;
import java.io.*;
import java.net.*;

public class FtpCommon
{
  public static HashMap<String, String> helpMap = new HashMap<String, String>();
  public static HashMap<String, String> cmdMap = new HashMap<String, String>();
  public enum Mode
  {
    Binary, Ascii
  }
  public enum Command
  {
    Ls, Lls, Put, Get, Lcd, Cd, Pwd, Lpwd, Mkdir, Lmkdir, Mput, Mget, Quit, Prompt, Help, /*!, ?,*/
    Append, Bell, Bye, Close, Delete, Debug, Dir, Disconnect, Glob, Hash, Literal, Mdelete,
    Mdir, Mls, Open, Recv, Remotehelp, Rename, Rmdir, Send, Status, Trace, Type, User, Verbose
  }
  public static boolean prompter = false;

  static
  { 
    cmdMap.put("!", "0");
    cmdMap.put("?", "1");
    cmdMap.put("append", "2");
    cmdMap.put("ascii", "3");
    cmdMap.put("bell", "4");
    cmdMap.put("binary", "5");
    cmdMap.put("bye", "6");
    cmdMap.put("cd", "7");
    cmdMap.put("close", "8");
    cmdMap.put("debug", "9");
    cmdMap.put("delete", "a");
    cmdMap.put("dir", "b");
    cmdMap.put("disconnect", "c");
    cmdMap.put("get", "d");
    cmdMap.put("glob", "e");
    cmdMap.put("hash", "f");
    cmdMap.put("help", "g");
    cmdMap.put("lcd", "h");
    cmdMap.put("lcwd", "i");
    cmdMap.put("literal", "j" );
    cmdMap.put("lls", "k");
    cmdMap.put("lmkdir", "l");
    cmdMap.put("lpwd", "m");
    cmdMap.put("ls", "n");
    cmdMap.put("mdelete", "o");
    cmdMap.put("mdir", "p");
    cmdMap.put("mget", "q");
    cmdMap.put("mkdir", "r");
    cmdMap.put("mls", "s");
    cmdMap.put("mput", "t");
    cmdMap.put("open", "u");
    cmdMap.put("prompt", "v");
    cmdMap.put("put", "w");
    cmdMap.put("pwd", "x");
    cmdMap.put("quit", "y");
    cmdMap.put("quote", "z");
    cmdMap.put("recv", "!");
    cmdMap.put("remotehelp", "@");
    cmdMap.put("rename", "#");
    cmdMap.put("rmdir", "$");
    cmdMap.put("send", "%");
    cmdMap.put("status", "^");
    cmdMap.put("trace", "&");
    cmdMap.put("type", "*");
    cmdMap.put("user", "(");
    cmdMap.put("verbose", ")");
    helpMap.put("binary", "files will be transferred in binary mode");
    helpMap.put("ascii", "files will be transferred in text mode");
    helpMap.put("ls", "list all files in the current directory on the server machine");
    helpMap.put("lls", "list all files in the current directory on the client machine");
    helpMap.put("put", "put <FileName> : upload <FileName> from client to server in the current mode");
    helpMap.put("get", "get <FileName> : download <FileName> from server to client");
    helpMap.put("cd", "change server directory\ncd .. : change to parent directory\ncd <Dir> : change to <Dir>");
    helpMap.put("lcd", "change client directory\nlcd .. : change to parent directory\nlcd <Dir> : change to <Dir>");
    helpMap.put("pwd", "displays current server directory");
    helpMap.put("lpwd", "displays current client directory");
    helpMap.put("mkdir", "mkdir <Dir> : make a subdirectory named <Dir> on server");
    helpMap.put("lmkdir", "lmkdir <Dir> : make a subdirectory named <Dir> on client");
    helpMap.put("mput", "mput <Pattern> : upload files on the server that match <Pattern>");
    helpMap.put("mget", "mget <Pattern> : download files on the client that match <Pattern>");
    helpMap.put("quit", "disconnect from the server");
    helpMap.put("prompt", "prompt on : turn prompt on for mput and mget\nprompt off: turn prompt off for mput and mget");
    helpMap.put("help" , "help [command] : explains the specified command if given, or lists all FTP commands");
    helpMap.put("!", "escapes to the shell");
    helpMap.put("?", "displays help information");
    helpMap.put("append", "append to a file");
    helpMap.put("bell", "beep when command completed");
    helpMap.put("bye" , "terminate ftp session and exit");
    helpMap.put("close", "terminate ftp session");
    helpMap.put("delete", "delete a file on the server");
    helpMap.put("debug", "toggle debugging mode");
    helpMap.put("dir", "dir <Dir> : lists contents of <Dir> if specified, or current directory");
    helpMap.put("disconnect", "terminate ftp session");
    helpMap.put("glob", "toggle metacharacter expansion of local file names");
    helpMap.put("hash", "toggle printing '#' for each buffered transfer");
    helpMap.put("literal", "send arbitrary ftp command");
    helpMap.put("mdelete", "delete multiple files");
    helpMap.put("mdir", "list contents of multiple directories");
    helpMap.put("mls", "list contents of multiple directories");
    helpMap.put("open", "connect to remote tftp");
    helpMap.put("recv", "receive file");
    helpMap.put("remotehelp", "get help from server");
    helpMap.put("rename", "rename a file");
    helpMap.put("rmdir", "remove directory on the server");
    helpMap.put("send", "send one file");
    helpMap.put("status", "show current status");
    helpMap.put("trace", "toggle packet tracing");
    helpMap.put("type", "set file transfer type");
    helpMap.put("user", "send new user information");
    helpMap.put("verbose", "toggle verbose mode");
  }

  //=========================================================

  public static void help(PrintWriter out)
  {
    Set<String> tempSet = FtpCommon.helpMap.keySet();
    TreeSet<String> helpSet = new TreeSet<String>();
    helpSet.addAll(tempSet);
    Iterator itr = helpSet.iterator();

    int i = 0;
    String temp[] = new String[helpMap.size()];

    while(itr.hasNext())
    {
      temp[i] = ((String)(itr.next()));
      i++;
    }

    for (int j = 0; j < 9; j++)
    {
      for (int k = 0; k < 5; k++)
      {
        if (j + (k * 9) < temp.length)
          out.printf("%15s",temp[j+(k*9)]);
      }
      out.printf("\n");
    }

    out.println("");
    out.flush();
  }

  //=========================================================

  public static void help(PrintWriter out, Object cmd)
  {
    if(helpMap.get(cmd) != null)
      out.printf("%s\n",helpMap.get(cmd).toString());
    else
      out.println("Invalid command");
    out.flush();
  }

  //=========================================================

  public static LinkedList<String> tokenizeString(String str)
  {
    LinkedList<String> list = new LinkedList<String>();
    StringTokenizer tok = new StringTokenizer(str, " ");
    while(tok.hasMoreTokens())
    {
      String temp = tok.nextToken().trim();
      if(temp.compareTo("") != 0)
        list.add(temp);
    }
    return list;
  }

  //=========================================================

  public static void sendCommand(String str, Socket socket)
  {
    PrintWriter out = null;
    try
    {
      str = "COMMAND:" + str;
      out = new PrintWriter(socket.getOutputStream(), true);
      out.println(str);
    }
    catch(IOException e)
    {
      System.out.printf("Exception: %s\n", e);
    }
  }

  //=========================================================

  public static boolean isValidCommand(String str)
  {
    return helpMap.containsKey(str);
  }

  //=========================================================
  
  public static boolean setPrompt(String str, PrintWriter out)
  {
    if (str.startsWith("on"))
      prompter = true;
    else if (str.startsWith("off"))
      prompter = false;
    else
      out.println("Invalid Command.\nUsage: prompt on/off");
      out.flush();
    return prompter;
  }

  //=========================================================
  
  public static boolean getPrompt()
  {
    return prompter;
  }
}
